import {
	IExecuteFunctions,
	INodeExecutionData,
	INodeType,
	INodeTypeDescription,
	NodeOperationError,
} from 'n8n-workflow';

import { SimpleJsonExtractor, JsonExtractionResult } from './SimpleJsonExtractor';

export class LLMJsonExtractor implements INodeType {
	description: INodeTypeDescription = {
		displayName: 'LLM JSON Extractor',
		name: 'llmJsonExtractor',
		icon: 'fa:code',
		group: ['transform'],
		version: 1,
		description: '从大模型输出中提取 JSON 数据，支持 Markdown 包裹和不标准格式',
		defaults: {
			name: 'LLM JSON Extractor',
		},
		inputs: ['main'],
		outputs: ['main'],
		properties: [
			{
				displayName: '输入字段',
				name: 'inputField',
				type: 'string',
				default: 'text',
				required: true,
				description: '包含大模型输出文本的字段名',
			},
			{
				displayName: '输出模式',
				name: 'outputMode',
				type: 'options',
				options: [
					{
						name: '第一个 JSON',
						value: 'first',
						description: '只提取第一个找到的 JSON 对象',
					},
					{
						name: '所有 JSON',
						value: 'all',
						description: '提取所有找到的 JSON 对象',
					},
				],
				default: 'first',
				description: '选择提取模式',
			},
			{
				displayName: '失败时的行为',
				name: 'onFailure',
				type: 'options',
				options: [
					{
						name: '抛出错误',
						value: 'error',
						description: '找不到 JSON 时抛出错误',
					},
					{
						name: '返回空对象',
						value: 'empty',
						description: '找不到 JSON 时返回空对象',
					},
					{
						name: '返回原始文本',
						value: 'original',
						description: '找不到 JSON 时返回原始文本',
					},
				],
				default: 'error',
				description: '当无法提取 JSON 时的处理方式',
			},
			{
				displayName: '包含元数据',
				name: 'includeMetadata',
				type: 'boolean',
				default: false,
				description: '是否在输出中包含提取过程的元数据信息',
			},
		],
	};

	async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
		const items = this.getInputData();
		const returnData: INodeExecutionData[] = [];

		const inputField = this.getNodeParameter('inputField', 0) as string;
		const outputMode = this.getNodeParameter('outputMode', 0) as string;
		const onFailure = this.getNodeParameter('onFailure', 0) as string;
		const includeMetadata = this.getNodeParameter('includeMetadata', 0) as boolean;

		// Helper function to handle failures
		const handleFailure = (onFailure: string, originalText: string, error: string): any => {
			switch (onFailure) {
				case 'empty':
					return {};
				case 'original':
					return { originalText, error };
				default:
					return { error };
			}
		};

		for (let i = 0; i < items.length; i++) {
			try {
				const item = items[i];
				const inputText = item.json[inputField] as string;

				if (!inputText || typeof inputText !== 'string') {
					if (onFailure === 'error') {
						throw new NodeOperationError(
							this.getNode(),
							`输入字段 "${inputField}" 不存在或不是字符串类型`,
							{ itemIndex: i }
						);
					} else {
						returnData.push({
							json: handleFailure(onFailure, inputText, 'Invalid input'),
						});
						continue;
					}
				}

				if (outputMode === 'all') {
					// 提取所有 JSON 对象
					const results = SimpleJsonExtractor.extractMultipleJson(inputText);
					
					if (results.length === 0) {
						if (onFailure === 'error') {
							throw new NodeOperationError(
								this.getNode(),
								'在输入文本中未找到任何有效的 JSON 数据',
								{ itemIndex: i }
							);
						} else {
							returnData.push({
								json: handleFailure(onFailure, inputText, 'No JSON found'),
							});
							continue;
						}
					}

					// 为每个找到的 JSON 创建一个输出项
					for (const result of results) {
						if (result.success) {
							const outputData: any = {
								...result.data,
							};

							if (includeMetadata) {
								outputData._metadata = {
									source: result.source,
									originalText: result.originalText,
									extractedText: result.extractedText,
								};
							}

							returnData.push({ json: outputData });
						}
					}
				} else {
					// 只提取第一个 JSON 对象
					const result = SimpleJsonExtractor.extractJson(inputText);

					if (!result.success) {
						if (onFailure === 'error') {
							throw new NodeOperationError(
								this.getNode(),
								`JSON 提取失败: ${result.error}`,
								{ itemIndex: i }
							);
						} else {
							returnData.push({
								json: handleFailure(onFailure, inputText, result.error || 'Unknown error'),
							});
							continue;
						}
					}

					const outputData: any = {
						...result.data,
					};

					if (includeMetadata) {
						outputData._metadata = {
							source: result.source,
							originalText: result.originalText,
							extractedText: result.extractedText,
						};
					}

					returnData.push({ json: outputData });
				}
			} catch (error) {
				if (this.continueOnFail()) {
					returnData.push({
						json: {
							error: error instanceof Error ? error.message : 'Unknown error',
						},
					});
					continue;
				}
				throw error;
			}
		}

		return [returnData];
	}


}

/**
 * 便捷函数：从大模型输出中提取 JSON
 */
export async function extractJsonFromLLMOutput(
	text: string,
	options: {
		multiple?: boolean;
		throwOnError?: boolean;
	} = {}
): Promise<any> {
	const { multiple = false, throwOnError = true } = options;

	if (multiple) {
		const results = SimpleJsonExtractor.extractMultipleJson(text);
		if (results.length === 0 && throwOnError) {
			throw new Error('No JSON found in the provided text');
		}
		return results.map(r => r.success ? r.data : null).filter(Boolean);
	} else {
		const result = SimpleJsonExtractor.extractJson(text);
		if (!result.success && throwOnError) {
			throw new Error(`JSON extraction failed: ${result.error}`);
		}
		return result.success ? result.data : null;
	}
}

/**
 * 便捷函数：检查文本是否包含 JSON
 */
export function containsJson(text: string): boolean {
	return SimpleJsonExtractor.containsJson(text);
}

/**
 * 便捷函数：获取 JSON 提取的详细结果
 */
export function getJsonExtractionDetails(text: string): JsonExtractionResult {
	return SimpleJsonExtractor.extractJson(text);
}
